/**
 *******************************************************************************
 * @FileName  : dfu_svc.c
 * @Author    : GaoQiu
 * @CreateDate: 2023年11月21日
 * @Copyright : Copyright(C) GaoQiu
 *              All Rights Reserved.
 *******************************************************************************
 *
 * The information contained herein is confidential and proprietary property of
 * GaoQiu and is available under the terms of Commercial License Agreement
 * between GaoQiu and the licensee in separate contract or the terms described
 * here-in.
 *
 * This heading MUST NOT be removed from this file.
 *
 * Licensees are granted free, non-transferable use of the information in this
 * file under Mutual Non-Disclosure Agreement. NO WARRENTY of ANY KIND is provided.
 *
 *******************************************************************************
 */

#include "stack/host/att_uuid.h"
#include "utils/byte_stream.h"
#include "stack/host/dm_api.h"
#include "svc_handle.h"

/*! Service UUID */             //LSB
static const uint8_t  dfuServiceUUID[] = {UINT16_TO_BYTES(0xFE59)};
static const uint16_t dfuSvcLen = sizeof(dfuServiceUUID);


/*! Characteristic  Declare */
//1. DFU Control Point //0x8EC9-0001-F315-4F60-9FB8-838830DAEA50
static const uint8_t dfuCtrlPointCharUUID[16] = {0x50, 0xEA, 0xDA, 0x30, 0x88, 0x83, 0xB8, 0x9F, 0x60, 0x4F, 0x15, 0xF3, 0x01, 0x00, 0xC9, 0x8E};

static const char_prop_t dfuCtrlPointProp = {
	.prop          = ATT_PROP_WRITE|ATT_PROP_NOTIFY,
	.attHandle     = DFU_CTRL_POINT_VAL_HDL,
	.UUID.UUID_128 = {0x50, 0xEA, 0xDA, 0x30, 0x88, 0x83, 0xB8, 0x9F, 0x60, 0x4F, 0x15, 0xF3, 0x01, 0x00, 0xC9, 0x8E},
};//use for Characteristic declaration

static const uint16_t dfuCtrlPointPropLen = sizeof(dfuCtrlPointProp);

static uint8_t  dfuCtrlPointVal = 0;
static uint16_t dfuCtrlPointValLen = sizeof(dfuCtrlPointVal);
#define DFU_CTRL_POINT_VAL_MAX_LEN   512

//CCCD
static uint8_t dfuCtrlPointClientCharValue[] = {UINT16_TO_BYTES(0x0000)};//default CCCD value = 0x0000; 0x0001->notify
static uint16_t dfuCtrlPointClientCharValueLen = sizeof(dfuCtrlPointClientCharValue);


/*! Characteristic  Declare */
//2. DFU Packet //0x8EC90002-F315-4F60-9FB8-838830DAEA50
static const uint8_t dfuPktCharUUID[16] = {0x50, 0xEA, 0xDA, 0x30, 0x88, 0x83, 0xB8, 0x9F, 0x60, 0x4F, 0x15, 0xF3, 0x02, 0x00, 0xC9, 0x8E};

static const char_prop_t dfuPktProp = {
	.prop          = ATT_PROP_WRITE_NO_RSP|ATT_PROP_NOTIFY,
	.attHandle     = DFU_PKT_VAL_HDL,
	.UUID.UUID_128 = {0x50, 0xEA, 0xDA, 0x30, 0x88, 0x83, 0xB8, 0x9F, 0x60, 0x4F, 0x15, 0xF3, 0x02, 0x00, 0xC9, 0x8E},
};//use for Characteristic declaration
static const uint16_t dfuPktPropLen = sizeof(dfuPktProp);

static uint8_t dfuPktVal = 0;
static uint16_t dfuPktValLen = sizeof(dfuPktVal);
#define DFU_PKT_VAL_MAX_LEN   512

//CCCD
static uint8_t dfuPktClientCharValue[] = {UINT16_TO_BYTES(0x0000)};//default CCCD value = 0x0000; 0x0001->notify
static uint16_t dfuPktClientCharValueLen = sizeof(dfuPktClientCharValue);


static const AttsAttr_t dfuAttrs[] =
{
	//Service
	GATT_CHARACTER_DEFINE(primSvcUuid, &dfuServiceUUID,    &dfuSvcLen, sizeof(dfuServiceUUID), ATTS_SET_NONE, ATTS_PERMIT_READ)

	// DFU Control Point
	GATT_CHARACTER_DEFINE(charDecUuid,          &dfuCtrlPointProp, &dfuCtrlPointPropLen, sizeof(dfuCtrlPointProp), ATTS_SET_NONE, ATTS_PERMIT_READ)
	GATT_CHARACTER_DEFINE(dfuCtrlPointCharUUID, &dfuCtrlPointVal,  &dfuCtrlPointValLen,  DFU_CTRL_POINT_VAL_MAX_LEN,  ATTS_SET_VARIABLE_LEN|ATTS_SET_WRITE_CBACK, ATTS_PERMIT_READ|ATTS_PERMIT_WRITE)
	GATT_CHARACTER_DEFINE(clientCharCfgUuid,    &dfuCtrlPointClientCharValue, &dfuCtrlPointClientCharValueLen, sizeof(dfuCtrlPointClientCharValue), ATTS_SET_CCC, ATTS_PERMIT_READ|ATTS_PERMIT_WRITE)

	// DFU Packet
	GATT_CHARACTER_DEFINE(charDecUuid,       &dfuPktProp, &dfuPktPropLen, sizeof(dfuPktProp), ATTS_SET_NONE, ATTS_PERMIT_READ)
	GATT_CHARACTER_DEFINE(dfuPktCharUUID,    &dfuPktVal,  &dfuPktValLen,  DFU_PKT_VAL_MAX_LEN,  ATTS_SET_VARIABLE_LEN|ATTS_SET_WRITE_CBACK, ATTS_PERMIT_READ|ATTS_PERMIT_WRITE)
	GATT_CHARACTER_DEFINE(clientCharCfgUuid, &dfuPktClientCharValue, &dfuPktClientCharValueLen, sizeof(dfuPktClientCharValue), ATTS_SET_CCC, ATTS_PERMIT_READ|ATTS_PERMIT_WRITE)
};


AttState_t DFU_WriteCback(uint16_t connHandle, uint16_t attHandle, uint8_t opcode, uint16_t offset,
		                 uint8_t *pValue, uint32_t len, AttsAttr_t* pAttr)
{
	switch(opcode)
	{
	case ATT_WRITE_CMD:
		APP_TRACK_INFO("ATT Write Cmd: attHandle:%d\r\n", attHandle);
		break;

	case ATT_WRITE_REQ:
		APP_TRACK_INFO("ATT Write Req: attHandle:%d\r\n", attHandle);
		break;

	case ATT_READ_REQ:
		APP_TRACK_INFO("ATT Read Req: attHandle:%d\r\n", attHandle);
		break;

	case ATT_READ_BLOB_REQ:
		APP_TRACK_INFO("ATT Read Blob Req: attHandle:%d\r\n", attHandle);
		break;

	default:
		break;
	}
	return ATT_SUCCESS;
}

AttsGroup_t dfuGrp = {
	.pNext       = NULL,
	.pAttr       = (AttsAttr_t *)&dfuAttrs[0],
	.readCback   = NULL,
	.writeCback  = DFU_WriteCback,
	.startHandle = DFU_SVC_START_HDL,
	.endHandle   = DFU_SVC_END_HDL,
};
